package b.gate.to.juhe

import java.net.URLEncoder
import java.nio.charset.Charset

import akka.NotUsed
import akka.actor.Actor
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model._
import akka.stream.{ActorMaterializer, OverflowStrategy}
import akka.stream.scaladsl.{BidiFlow, Sink, Source}
import akka.util.ByteString
import org.squbs.httpclient.ClientFlow
import org.squbs.unicomplex.RouteDefinition
import spray.json._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.{Duration, FiniteDuration}
import scala.concurrent.{Await, Future}
import scala.util.Try

/**
  * Created by lenovo on 2017/1/1.
  */
case class CC聚合数据应答(resultcode: String, reason: String)
case class CC总线应答(v应答码: Int, v应答信息: String)
trait T聚合数据JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
  implicit val f1: RootJsonFormat[CC聚合数据应答] = jsonFormat2(CC聚合数据应答)
  implicit val f2: RootJsonFormat[CC总线应答] = jsonFormat2(CC总线应答)
}
trait C天气服务方 extends T聚合数据JsonSupport { this: RouteDefinition =>
  implicit val materializer = ActorMaterializer()
  private[this] val pool = ClientFlow[NotUsed]("juhe")(context.system, materializer)
  private[this] val failedData = Source.single[ByteString](ByteString("{}"))
  private[this] val failedEntity = HttpEntity(ContentTypes.`application/json`, failedData)
  private[this] val failedResponse = HttpResponse(StatusCodes.InternalServerError, entity = failedEntity)
  def call(uri: String): Future[Source[ByteString, Any]] = {
    val response = Source.single(HttpRequest(uri = uri) -> NotUsed).via(pool).runWith(Sink.head)
    response.map(_._1.getOrElse(failedResponse)).map(_.entity.dataBytes)
  }
  def to服务方(v城市: String): (HttpRequest, NotUsed) = {
    val x城市 = URLEncoder.encode(v城市, "UTF-8")
    val uri = s"/weather/index?cityname=$x城市&key=542bbe7c227fdd2ba8e812f99b4c239e"
    HttpRequest(uri = uri) -> NotUsed
  }
  private[this] val v服务方失败 = CC总线应答(StatusCodes.InternalServerError.intValue, "服务方调用失败")
  def from服务方(v服务方应答: (Try[HttpResponse], NotUsed)): Source[ByteString, Any] = {
    v服务方应答._1.getOrElse(failedResponse).entity.dataBytes
  }
  def from服务方X(v服务方应答: (Try[HttpResponse], NotUsed)): Source[ByteString, Any] = {
    val rsPck = v服务方应答._1.getOrElse(failedResponse).entity.dataBytes.fold(ByteString(""))(_ ++ _).map(_.utf8String)
    rsPck.map { pck =>
      println("pck: " + pck)
      val json = pck.parseJson
      val v应答 = json.convertTo[CC聚合数据应答]
      println("from: " + v应答)
      val x应答 = CC总线应答(v应答.resultcode.toInt, v应答.reason)
      ByteString(x应答.toJson.toString())
    }
  }
  private[this] val codec = BidiFlow.fromFunctions(to服务方, from服务方X)
  private[this] val round = codec.join(pool)
  //private[this] val actor = Source.actorRef[String](1, OverflowStrategy.fail)
  //actor.via(round).runWith(Sink.seq)
  def callx(v城市: String) = {
    Source.single[String](v城市).via(round).runWith(Sink.head)
  }
}
